﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Jitter;
using ShevaEngine.Core.Modules.Scenes;
using ShevaEngine.Core.Modules.Graphics;
using Microsoft.Xna.Framework;
using ShevaEngine.Core.Modules.Graphics.Cameras;
using Jitter.Dynamics;
using Microsoft.Xna.Framework.Graphics;
using ShevaEngine.Core.Modules.Materials;

namespace ShevaEngine2JitterLayer
{
    /// <summary>
    /// Debug drawer.
    /// </summary>
    public class XnaDebugDrawer : GraphicsSceneObject, IDebugDrawer
    {
        /// <summary>Physics world.</summary>
        private World PhysicsWorld;
        /// <summary>Triangles.</summary>
        private VertexPositionColor[] Triangles;
        /// <summary>Triangles indexer.</summary>
        private Int32 TrianglesIndexer;
        /// <summary>Draw call key.</summary>
        private DrawCallKey DrawCallKey;

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="physicsWorld"></param>
        public XnaDebugDrawer(World physicsWorld)
            : base(null)
        {
            this.PhysicsWorld = physicsWorld;

            this.DrawCallKey = new DrawCallKey(
                MaterialManager.Instance.GetMaterialID("MaterialBaseVertexColor"),
                DrawCallKey.None, DrawCallKey.None, DrawCallKey.None);

            this.Triangles = new VertexPositionColor[32];

            for (int i = 0; i < this.Triangles.Length; i++)
                this.Triangles[i] = new VertexPositionColor(Vector3.Zero, Color.YellowGreen);
        }

        /// <summary>
        /// Add in rendering pipeline.
        /// </summary>
        /// <param name="renderingPipeline"></param>
        /// <param name="camera"></param>
        public override void AddInRenderingPipeline(RenderingPipeline renderingPipeline, Camera camera)
        {
            if (this.Visible)
            {
                this.TrianglesIndexer = 0;

                foreach (RigidBody body in this.PhysicsWorld.RigidBodies)
                    body.DebugDraw(this);

                if (this.TrianglesIndexer > 0)
                    renderingPipeline.AddOpaqueGraphicsObject(this.DrawCallKey,
                        new UserPrimitivesDrawCall<VertexPositionColor>(PrimitiveType.TriangleList, this.Triangles, this.TrianglesIndexer / 3), Matrix.Identity);
            }
        }

        /// <summary>
        /// Add in rendering pipeline.
        /// </summary>
        /// <param name="renderingPipeline"></param>
        /// <param name="position"></param>
        /// <param name="distance"></param>
        public override void AddInRenderingPipeline(RenderingPipeline renderingPipeline, Vector3 position, float distance)
        {
            if (this.Visible)
            {
                this.TrianglesIndexer = 0;

                foreach (RigidBody body in this.PhysicsWorld.RigidBodies)
                    body.DebugDraw(this);

                if (this.TrianglesIndexer > 0)
                    renderingPipeline.AddOpaqueGraphicsObject(this.DrawCallKey,
                        new UserPrimitivesDrawCall<VertexPositionColor>(PrimitiveType.LineList, this.Triangles, this.TrianglesIndexer / 3), Matrix.Identity);
            }
        }
        

        /// <summary>
        /// Draw line.
        /// </summary>
        /// <param name="start"></param>
        /// <param name="end"></param>
        public void DrawLine(Jitter.LinearMath.JVector start, Jitter.LinearMath.JVector end)
        {
            
        }

        /// <summary>
        /// Draw point.
        /// </summary>
        /// <param name="pos"></param>
        public void DrawPoint(Jitter.LinearMath.JVector pos)
        {
            
        }

        /// <summary>
        /// Draw triangle.
        /// </summary>
        /// <param name="pos1"></param>
        /// <param name="pos2"></param>
        /// <param name="pos3"></param>
        public void DrawTriangle(Jitter.LinearMath.JVector pos1, Jitter.LinearMath.JVector pos2, Jitter.LinearMath.JVector pos3)
        {
            if (this.Triangles.Length <= (this.TrianglesIndexer + 6))
            {
                Array.Resize<VertexPositionColor>(ref this.Triangles, this.Triangles.Length * 2);

                for (int i = this.TrianglesIndexer; i < this.Triangles.Length; i++)
                    this.Triangles[i] = new VertexPositionColor(Vector3.Zero, Color.YellowGreen);
            }

            this.Triangles[this.TrianglesIndexer++].Position = Conversions.ToXNAVector(pos1);
            this.Triangles[this.TrianglesIndexer++].Position = Conversions.ToXNAVector(pos2);
            this.Triangles[this.TrianglesIndexer++].Position = Conversions.ToXNAVector(pos3);            
        }
    }
}
